package org.robot.scm.platform;

import java.lang.reflect.Constructor;
import java.util.List;
import java.util.Set;
import lombok.SneakyThrows;
import org.reflections.Reflections;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.robot.scm.utils.StreamUtils;

/**
 * 父类实例化所有继承子类反射工具
 *
 * @Author : Awn create on 2024/4/22 16:04
 */
public class ReflectionLoader {

    public static <T> List<? extends T> load(Class<T> clazz) {
        String packageName = clazz.getPackage().getName();
        Reflections reflections = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage(packageName)));
        Set<Class<? extends T>> subClasses = reflections.getSubTypesOf(clazz);
        List<? extends Constructor<? extends T>> constructors = StreamUtils.convert(subClasses, ReflectionLoader::getConstructor);
        return StreamUtils.convert(constructors, ReflectionLoader::newInstance);
    }

    private static <T> T newInstance(Constructor<? extends T> constructor) {
        try {
            return constructor.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static <T> Constructor<? extends T> getConstructor(Class<? extends T> e) {
        try {
            return e.getDeclaredConstructor();
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(ex);
        }
    }

}
